/**********************************
 * @Description: MongoDB服务
 * @Author: Ronnie Zhang
 * @LastEditor: Ronnie Zhang
 * @LastEditTime: 2023/12/07 20:30:00
 * @Email: zclzone@outlook.com
 * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
 **********************************/

import { Injectable, Logger } from '@nestjs/common';
import { InjectConnection } from '@nestjs/mongoose';
import { Connection } from 'mongoose';

@Injectable()
export class MongoService {
  private readonly logger = new Logger(MongoService.name);

  constructor(@InjectConnection() private connection: Connection) {}

  /**
   * 获取MongoDB连接状态
   */
  getConnectionStatus() {
    const states = {
      0: 'disconnected',
      1: 'connected',
      2: 'connecting',
      3: 'disconnecting',
    };
    return {
      state: states[this.connection.readyState],
      readyState: this.connection.readyState,
      host: this.connection.host,
      port: this.connection.port,
      name: this.connection.name,
    };
  }

  /**
   * 检查MongoDB连接是否正常
   */
  async isConnected(): Promise<boolean> {
    try {
      return this.connection.readyState === 1;
    } catch (error) {
      this.logger.error('MongoDB连接检查失败:', error);
      return false;
    }
  }

  /**
   * 获取数据库实例
   */
  getDatabase(): any {
    return this.connection.db;
  }

  /**
   * 获取集合
   */
  getCollection(name: string): any {
    return this.connection.db.collection(name);
  }

  /**
   * 创建集合
   */
  async createCollection(name: string, options?: any): Promise<any> {
    try {
      return await this.connection.db.createCollection(name, options);
    } catch (error) {
      this.logger.error(`创建集合 ${name} 失败:`, error);
      throw error;
    }
  }

  /**
   * 删除集合
   */
  async dropCollection(name: string): Promise<any> {
    try {
      return await this.connection.db.collection(name).drop();
    } catch (error) {
      this.logger.error(`删除集合 ${name} 失败:`, error);
      throw error;
    }
  }

  /**
   * 列出所有集合
   */
  async listCollections(): Promise<any[]> {
    try {
      return await this.connection.db.listCollections().toArray();
    } catch (error) {
      this.logger.error('获取集合列表失败:', error);
      throw error;
    }
  }

  /**
   * 执行数据库命令
   */
  async runCommand(command: any): Promise<any> {
    try {
      return await this.connection.db.command(command);
    } catch (error) {
      this.logger.error('执行数据库命令失败:', error);
      throw error;
    }
  }

  /**
   * 获取数据库统计信息
   */
  async getStats(): Promise<any> {
    try {
      return await this.connection.db.stats();
    } catch (error) {
      this.logger.error('获取数据库统计信息失败:', error);
      throw error;
    }
  }

  /**
   * 创建索引
   */
  async createIndex(collectionName: string, indexSpec: any, options?: any): Promise<any> {
    try {
      const collection = this.getCollection(collectionName);
      return await collection.createIndex(indexSpec, options);
    } catch (error) {
      this.logger.error(`在集合 ${collectionName} 创建索引失败:`, error);
      throw error;
    }
  }

  /**
   * 删除索引
   */
  async dropIndex(collectionName: string, indexName: string): Promise<any> {
    try {
      const collection = this.getCollection(collectionName);
      return await collection.dropIndex(indexName);
    } catch (error) {
      this.logger.error(`在集合 ${collectionName} 删除索引失败:`, error);
      throw error;
    }
  }

  /**
   * 获取集合索引
   */
  async listIndexes(collectionName: string): Promise<any[]> {
    try {
      const collection = this.getCollection(collectionName);
      return await collection.listIndexes().toArray();
    } catch (error) {
      this.logger.error(`获取集合 ${collectionName} 索引失败:`, error);
      throw error;
    }
  }

  /**
   * 执行聚合操作
   */
  async aggregate(collectionName: string, pipeline: any[]): Promise<any[]> {
    try {
      const collection = this.getCollection(collectionName);
      return await collection.aggregate(pipeline).toArray();
    } catch (error) {
      this.logger.error(`在集合 ${collectionName} 执行聚合操作失败:`, error);
      throw error;
    }
  }

  /**
   * 执行原生查询
   */
  async find(collectionName: string, query: any = {}, options: any = {}): Promise<any[]> {
    try {
      const collection = this.getCollection(collectionName);
      return await collection.find(query, options).toArray();
    } catch (error) {
      this.logger.error(`在集合 ${collectionName} 执行查询失败:`, error);
      throw error;
    }
  }

  /**
   * 插入文档
   */
  async insertOne(collectionName: string, document: any): Promise<any> {
    try {
      const collection = this.getCollection(collectionName);
      return await collection.insertOne(document);
    } catch (error) {
      this.logger.error(`在集合 ${collectionName} 插入文档失败:`, error);
      throw error;
    }
  }

  /**
   * 批量插入文档
   */
  async insertMany(collectionName: string, documents: any[]): Promise<any> {
    try {
      const collection = this.getCollection(collectionName);
      return await collection.insertMany(documents);
    } catch (error) {
      this.logger.error(`在集合 ${collectionName} 批量插入文档失败:`, error);
      throw error;
    }
  }

  /**
   * 更新文档
   */
  async updateOne(collectionName: string, filter: any, update: any, options: any = {}): Promise<any> {
    try {
      const collection = this.getCollection(collectionName);
      return await collection.updateOne(filter, update, options);
    } catch (error) {
      this.logger.error(`在集合 ${collectionName} 更新文档失败:`, error);
      throw error;
    }
  }

  /**
   * 批量更新文档
   */
  async updateMany(collectionName: string, filter: any, update: any, options: any = {}): Promise<any> {
    try {
      const collection = this.getCollection(collectionName);
      return await collection.updateMany(filter, update, options);
    } catch (error) {
      this.logger.error(`在集合 ${collectionName} 批量更新文档失败:`, error);
      throw error;
    }
  }

  /**
   * 删除文档
   */
  async deleteOne(collectionName: string, filter: any): Promise<any> {
    try {
      const collection = this.getCollection(collectionName);
      return await collection.deleteOne(filter);
    } catch (error) {
      this.logger.error(`在集合 ${collectionName} 删除文档失败:`, error);
      throw error;
    }
  }

  /**
   * 批量删除文档
   */
  async deleteMany(collectionName: string, filter: any): Promise<any> {
    try {
      const collection = this.getCollection(collectionName);
      return await collection.deleteMany(filter);
    } catch (error) {
      this.logger.error(`在集合 ${collectionName} 批量删除文档失败:`, error);
      throw error;
    }
  }

  /**
   * 计数文档
   */
  async countDocuments(collectionName: string, filter: any = {}): Promise<number> {
    try {
      const collection = this.getCollection(collectionName);
      return await collection.countDocuments(filter);
    } catch (error) {
      this.logger.error(`在集合 ${collectionName} 计数文档失败:`, error);
      throw error;
    }
  }

  /**
   * 分页查询
   */
  async findWithPagination(
    collectionName: string,
    query: any = {},
    options: any = {},
    page: number = 1,
    limit: number = 10,
  ): Promise<{
    data: any[];
    total: number;
    page: number;
    limit: number;
    totalPages: number;
  }> {
    try {
      const collection = this.getCollection(collectionName);
      const skip = (page - 1) * limit;
      
      const [data, total] = await Promise.all([
        collection.find(query, { ...options, skip, limit }).toArray(),
        collection.countDocuments(query),
      ]);

      return {
        data,
        total,
        page,
        limit,
        totalPages: Math.ceil(total / limit),
      };
    } catch (error) {
      this.logger.error(`在集合 ${collectionName} 分页查询失败:`, error);
      throw error;
    }
  }
}
